home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / src / dlg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  20.9 KB  |  1,002 lines

  1. /* Dlg box features module for the Midnight Commander
  2.    Copyright (C) 1994, 1995 Radek Doulik, Miguel de Icaza
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18.  
  19. #include <config.h>
  20. /* "$Id: dlg.c,v 1.3 1995/02/21 19:05:40 miguel Exp $" */
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <malloc.h>
  24. #include "tty.h"
  25. #include <stdarg.h>
  26. #include "mad.h"
  27. #include "util.h"
  28. #include "menu.h"
  29. #include "global.h"
  30. #include "win.h"
  31. #include "color.h"
  32. #include "mouse.h"
  33. #include "help.h"
  34. #include "key.h"    /* For mi_getch() */
  35. #include "dlg.h"
  36. #include "dialog.h"    /* For push_refresh() and pop_refresh() */
  37. #include "layout.h"
  38. #include "main.h"    
  39. #ifdef HAVE_XVIEW
  40. #   include "xvmain.h"
  41. #endif
  42. #ifdef HAVE_TK
  43. #    include "tkmain.h"
  44.  
  45. /* This is the current frame, used to group Tk packings */
  46. char *the_frame = "";
  47.  
  48. #endif
  49.  
  50. #define waddc(w,y1,x1,c) move (w->y+y1, w->x+x1); addch (c)
  51.  
  52. #ifdef HAVE_X
  53. extern Dlg_head *midnight_dlg;
  54. #endif
  55.  
  56. /* Primitive way to check if the the current dialog is our dialog */
  57. /* This is needed by async routines like load_prompt */
  58. Dlg_head *current_dlg = 0;
  59.  
  60. /* A hook list for idle events */
  61. Hook *idle_hook = 0;
  62.  
  63. static void slow_box (Dlg_head *h, int y, int x, int ys, int xs)
  64. {
  65.     move (h->y+y, h->x+x);
  66.     hline (' ', xs);
  67.     vline (' ', ys);
  68.     move (h->y+y, h->x+x+xs-1);
  69.     vline (' ', ys);
  70.     move (h->y+y+ys-1, h->x+x);
  71.     hline (' ', xs);
  72. }
  73.  
  74. /* draw box in window */
  75. void draw_box (Dlg_head *h, int y, int x, int ys, int xs)
  76. {
  77.     extern int slow_terminal;
  78.     
  79.     if (slow_terminal){
  80.     slow_box (h, y, x, ys, xs);
  81.     return;
  82.     }
  83.     
  84. #ifndef HAVE_SLANG
  85.     waddc (h, y, x, ACS_ULCORNER);
  86.     hline (ACS_HLINE, xs - 2);
  87.     waddc (h, y + ys - 1, x, ACS_LLCORNER);
  88.     hline (ACS_HLINE, xs - 2);
  89.  
  90.     waddc (h, y, x + xs - 1, ACS_URCORNER);
  91.     waddc (h, y + ys - 1, x + xs - 1, ACS_LRCORNER);
  92.  
  93.     move (h->y+y+1, h->x+x);
  94.     vline (ACS_VLINE, ys - 2);
  95.     move (h->y+y+1, h->x+x+xs-1);
  96.     vline (ACS_VLINE, ys - 2);
  97. #else
  98.     SLsmg_draw_box (h->y+y, h->x+x, ys, xs);
  99. #endif
  100. }
  101.  
  102. /* draw box in window */
  103. void draw_double_box (Dlg_head *h, int y, int x, int ys, int xs)
  104. {
  105. #ifndef HAVE_SLANG
  106.     draw_box (h, y, x, ys, xs);
  107. #else
  108.     SLsmg_draw_double_box (h->y+y, h->x+x, ys, xs);
  109. #endif
  110. }
  111.  
  112. void widget_erase (Widget *w)
  113. {
  114.     int x, y;
  115.  
  116.     for (y = 0; y < w->lines; y++){
  117.     widget_move (w, y, 0);
  118.     for (x = 0; x < w->cols; x++)
  119.         addch (' ');
  120.     }
  121. }
  122.  
  123. void dlg_erase (Dlg_head *h)
  124. {
  125.     int x, y;
  126.  
  127.     for (y = 0; y < h->lines; y++){
  128.     move (y+h->y, h->x);
  129.     for (x = 0; x < h->cols; x++){
  130.         addch (' ');
  131.     }
  132.     }
  133. }
  134.  
  135. void init_widget (Widget *w, int y, int x, int lines, int cols,
  136.           int (*callback)(Dlg_head *, void *, int, int),
  137.           destroy_fn destroy, mouse_h mouse_handler)
  138. {
  139.     w->x = x;
  140.     w->y = y;
  141.     w->cols = cols;
  142.     w->lines = lines;
  143.     w->color = -1;
  144.     w->callback = callback;
  145.     w->destroy  = destroy;
  146.     w->mouse = mouse_handler;
  147.     w->wdata = 0;
  148.     w->wcontainer = 0;
  149.     w->frame = "";
  150.     w->parent = 0;
  151.     /* Almost all widgets want to put the cursor in a suitable place */
  152.     w->options = W_WANT_CURSOR; 
  153. }
  154.  
  155. int default_proc (Dlg_head *h, int Msg, int Par)
  156. {
  157.     switch (Msg){
  158.  
  159.     case WIDGET_HOTKEY:         /* Didn't use the key */
  160.         return 0;
  161.  
  162.     case WIDGET_INIT:        /* We could tell if something went wrong */
  163.     return 1;
  164.     
  165.     case WIDGET_KEY:
  166.     return 0;        /* Didn't use the key */
  167.     
  168.     case WIDGET_FOCUS:        /* We accept FOCUSes */
  169. #ifdef HAVE_TK
  170.     if (h->current){
  171.         tk_evalf ("focus %s", ((char *)(h->current->widget->wdata))+1);
  172.     }
  173. #endif
  174.     return 1;
  175.     
  176.     case WIDGET_UNFOCUS:    /* We accept loose FOCUSes */
  177.     return 1;
  178.     
  179.     case WIDGET_DRAW:
  180.     return 1;
  181.  
  182.     case WIDGET_DESTROY:
  183.     return 1;
  184.  
  185.     case WIDGET_CURSOR:
  186.     /* Move the cursor to the default widget position */
  187.     return 1;
  188.  
  189.     case WIDGET_IDLE:
  190.     return 1;
  191.     }
  192.     printf ("Internal error: unhandled message: %d\n", Msg);
  193.     return 1;
  194. }
  195.  
  196. int default_dlg_callback (Dlg_head *h, int id, int msg)
  197. {
  198.     if (msg == DLG_IDLE){
  199.     dlg_broadcast_msg_to (h, WIDGET_IDLE, 0, W_WANT_IDLE);
  200.     }
  201.     return 0;
  202. }
  203.  
  204. #ifdef HAVE_X
  205. int midnight_callback (struct Dlg_head *h, int id, int msg);
  206. #endif
  207. Dlg_head *create_dlg (int y1, int x1, int lines, int cols,
  208.               int *color_set,
  209.               int (*callback) (struct Dlg_head *, int, int),
  210.               char *help_ctx, char *name,
  211.               int flags)
  212. {
  213.     Dlg_head *new_d;
  214.  
  215.     if (flags & DLG_CENTER){
  216.     y1 = (LINES-lines)/2;
  217.     x1 = (COLS-cols)/2;
  218.     }
  219.     if ((flags & DLG_TRYUP) && (y1 > 3))
  220.     y1 -= 2;
  221.     
  222.     new_d = (Dlg_head *) malloc (sizeof (Dlg_head));
  223.     new_d->current = NULL;
  224.     new_d->count = 0;
  225.     new_d->direction = DIR_FORWARD;
  226.     new_d->color = color_set;
  227.     new_d->help_ctx = help_ctx;
  228.     new_d->callback = callback ? callback : default_dlg_callback;
  229.     new_d->send_idle_msg = 0;
  230.     new_d->x = x1;
  231.     new_d->y = y1;
  232.     new_d->title = 0;
  233.     new_d->cols = cols;
  234.     new_d->lines = lines;
  235.     new_d->refresh_pushed = 0;
  236.     new_d->has_menubar = 0;
  237.     new_d->name = name;
  238.     new_d->raw = 0;
  239.     new_d->initfocus = NULL;
  240. #ifdef HAVE_X
  241.     if (callback != midnight_callback)
  242.         new_d->wdata = xtoolkit_create_dialog (new_d);
  243.     else
  244.         new_d->wdata = xtoolkit_get_main_dialog (new_d);
  245. #endif    
  246.     return (new_d);
  247. }
  248.               
  249. void set_idle_proc (Dlg_head *d, int state)
  250. {
  251.     d->send_idle_msg = state;
  252. }
  253.  
  254. /* add component to dialog buffer */
  255. int add_widgetl (Dlg_head *where, void *what, WLay layout)
  256. {
  257.     Widget_Item *back;
  258.     Widget      *widget = (Widget *) what;
  259.  
  260. #ifdef HAVE_TK
  261.     widget->frame = the_frame;
  262. #endif
  263.     
  264.     widget->layout = layout;
  265.     /* Don't accept 0 widgets, this could be from widgets that could not */
  266.     /* initialize properly */
  267.     if (!what)
  268.     return 0;
  269.  
  270.     widget->x += where->x;
  271.     widget->y += where->y;
  272.     
  273.     back = where->current;
  274.     where->current = (Widget_Item *) malloc (sizeof (Widget_Item));
  275.     if (back){
  276.     back->prev = where->current;
  277.     where->current->next = back;
  278.     } else {
  279.     where->current->next = where->current;
  280.     where->first = where->current;
  281.     }
  282.  
  283.     where->current->dlg_id = where->count;
  284.     where->current->prev = where->first;
  285.     where->last = where->current;
  286.     where->first->next = where->last;
  287.  
  288.     where->current->widget = what;
  289.     where->current->widget->parent = where;
  290.  
  291.     where->count++;
  292.     return (where->count - 1);
  293. }
  294.  
  295. int add_widget (Dlg_head *where, void *what)
  296. {
  297.     return add_widgetl (where, what, XV_WLAY_DONTCARE);
  298. }
  299.  
  300. int send_message (Dlg_head *h, Widget *w, int msg, int par)
  301. {
  302.     return (*(w->callback))(h, w, msg, par);
  303. }
  304.  
  305. /* broadcast a message to all the widgets in a dialog that have
  306.  * the options set to flags.
  307.  */
  308. void dlg_broadcast_msg_to (Dlg_head *h, int message, int reverse, int flags)
  309. {
  310.     Widget_Item *p, *first;
  311.  
  312.     if (reverse)
  313.     first = p = h->current->prev;
  314.     else
  315.     /* FIXME: On XView the layout for the widget->next widget is
  316.        invoked, and we should change the buttons order on query_dialog
  317.        in order to use the HAVE_X part of the statement */
  318. #ifdef HAVE_X
  319.     first = p = h->current;
  320. #else
  321.     first = p = h->current->next;
  322. #endif
  323.     do {
  324. /*    if (p->widget->options & flags) */
  325.         send_message (h, p->widget, message, 0);
  326.  
  327.     if (reverse)
  328.         p = p->prev;
  329.     else
  330.         p = p->next;
  331.     } while (first != p);
  332. }
  333.  
  334. /* broadcast a message to all the widgets in a dialog */
  335. void dlg_broadcast_msg (Dlg_head *h, int message, int reverse)
  336. {
  337.     dlg_broadcast_msg_to (h, message, reverse, ~0);
  338. }
  339.  
  340. int dlg_focus (Dlg_head *h)
  341. {
  342.     if (send_message (h, h->current->widget, WIDGET_FOCUS, 0)){
  343.     (*h->callback) (h, h->current->dlg_id, DLG_FOCUS);
  344.     return 1;
  345.     }
  346.     return 0;
  347. }
  348.  
  349. int dlg_unfocus (Dlg_head *h)
  350. {
  351.     if (send_message (h, h->current->widget, WIDGET_UNFOCUS, 0)){
  352.     (*h->callback) (h, h->current->dlg_id, DLG_UNFOCUS);
  353.     return 1;
  354.     }
  355.     return 0;
  356. }
  357.  
  358. static void select_a_widget (Dlg_head *h, int down)
  359. {
  360.     int direction = h->direction;
  361.  
  362.     if (!down)
  363.     direction = !direction;
  364.     
  365.     do {
  366.     if (direction)
  367.         h->current = h->current->next;
  368.     else
  369.         h->current = h->current->prev;
  370.     
  371.     (*h->callback) (h, h->current->dlg_id, DLG_ONE_DOWN);
  372.     } while (!dlg_focus (h));
  373. }
  374.  
  375. /* Return true if the windows overlap */
  376. int dlg_overlap (Widget *a, Widget *b)
  377. {
  378.     if ((b->x >= a->x + a->cols)
  379.     || (a->x >= b->x + b->cols)
  380.     || (b->y >= a->y + a->lines)
  381.     || (a->y >= b->y + b->lines))
  382.     return 0;
  383.     return 1;
  384. }
  385.  
  386.  
  387. /* Searches a widget, uses the callback as a signature in the dialog h */
  388. Widget *find_widget_type (Dlg_head *h, callback_fn signature)
  389. {
  390.     Widget *w;
  391.     Widget_Item *item;
  392.     int i;
  393.  
  394.     if (!h)
  395.     return 0;
  396.     
  397.     w = 0;
  398.     for (i = 0, item = h->current; i < h->count; i++, item = item->next){
  399.     if (item->widget->callback == signature){
  400.         w = item->widget;
  401.         break;
  402.     }
  403.     }
  404.     return w;
  405. }
  406.  
  407. void dlg_one_up (Dlg_head *h)
  408. {
  409.     Widget_Item *old;
  410.  
  411.     old = h->current;
  412.     /* If it accepts unFOCUSion */
  413.     if (!dlg_unfocus(h))
  414.     return;
  415.     
  416.     select_a_widget (h, 0);
  417.     if (dlg_overlap (old->widget, h->current->widget)){
  418.     send_message (h, h->current->widget, WIDGET_DRAW, 0);
  419.     send_message (h, h->current->widget, WIDGET_FOCUS, 0);
  420.     }
  421. }
  422.  
  423. void dlg_one_down (Dlg_head *h)
  424. {
  425.     Widget_Item *old;
  426.  
  427.     old = h->current;
  428.     if (!dlg_unfocus (h))
  429.     return;
  430.  
  431.     select_a_widget (h, 1); 
  432.     if (dlg_overlap (old->widget, h->current->widget)){
  433.     send_message (h, h->current->widget, WIDGET_DRAW, 0);
  434.     send_message (h, h->current->widget, WIDGET_FOCUS, 0);
  435.     }
  436. }
  437.  
  438. int dlg_select_widget (Dlg_head *h, void *w)
  439. {
  440.     if (dlg_unfocus (h)){
  441.     while (h->current->widget != w)
  442.         h->current = h->current->next;
  443.     while (!dlg_focus (h))
  444.         h->current = h->current->next;
  445.  
  446.     return 1;
  447.     }
  448.     return 0;
  449. }
  450.  
  451. int send_message_to (Dlg_head *h, Widget *w, int msg, int par)
  452. {
  453.     Widget_Item *p = h->current;
  454.     int v, i;
  455.  
  456.     v = 0;
  457.     for (i = 0; i < h->count; i++){
  458.     if (w == (void *) p->widget){
  459.         v = send_message (h, p->widget, msg, par);
  460.         break;
  461.     }
  462.     p = p->next;
  463.     }
  464.     return v;
  465. }
  466.  
  467. #define callback(h) (h->current->widget->callback)
  468.  
  469. void update_cursor (Dlg_head *h)
  470. {
  471.     if (h->current->widget->options & W_WANT_CURSOR)
  472.     send_message (h, h->current->widget, WIDGET_CURSOR, 0);
  473.     else {
  474.     Widget_Item *p = h->current;
  475.     
  476.     do {
  477.         if (p->widget->options & W_WANT_CURSOR)
  478.         if ((*p->widget->callback)(h, p->widget, WIDGET_CURSOR, 0)){
  479. #ifdef HAVE_TK
  480.             tk_focus_widget (p);
  481. #endif
  482.             break;
  483.         }
  484.         p = p->next;
  485.     } while (h->current != p);
  486.     }
  487. }
  488.  
  489. void dlg_redraw (Dlg_head *h)
  490. {
  491.     (h->callback)(h, 0, DLG_DRAW);
  492.  
  493.     /* Redraw the widgets in reverse order, leaving the current widget
  494.        as the last one */
  495.     dlg_broadcast_msg (h, WIDGET_DRAW, 1);
  496.     
  497.     update_cursor (h);
  498. }
  499.  
  500. void dlg_refresh (void *parameter)
  501. {
  502.     extern void clr_scr ();
  503.  
  504.     dlg_redraw ((Dlg_head *) parameter);
  505. }
  506.  
  507. static INLINE void dialog_handle_key (Dlg_head *h, int d_key)
  508. {
  509.     switch (d_key){
  510.     case KEY_LEFT:
  511.     case KEY_UP:
  512.     dlg_one_up (h);
  513.     break;
  514.     
  515.     case KEY_RIGHT:
  516.     case KEY_DOWN:
  517.     dlg_one_down (h);
  518.     break;
  519.  
  520.     case KEY_F(1):
  521.     interactive_display (LIBDIR "mc.hlp", h->help_ctx);
  522.     do_refresh ();
  523.     break;
  524.  
  525.     case XCTRL('z'):
  526.     suspend_cmd ();
  527.     /* Fall through */
  528.         
  529.     case XCTRL('l'):
  530. #ifndef HAVE_SLANG
  531.     /* Use this is the refreshes fail */
  532.     clr_scr ();
  533.     do_refresh ();
  534. #else
  535.     touchwin (stdscr);
  536. #endif
  537.     refresh ();
  538.     doupdate ();
  539.     break;
  540.     
  541.     case '\n':
  542.     case KEY_ENTER:
  543.     h->ret_value = B_ENTER;
  544.     h->running = 0;
  545.     break;
  546.  
  547.     case ESC_CHAR:
  548.     case KEY_F (10):
  549.     case XCTRL ('c'):
  550.     case XCTRL ('g'):
  551.     h->running = 0;
  552.     h->ret_value = B_CANCEL;
  553.     break;
  554.     }
  555. }
  556.  
  557. static int dlg_try_hotkey (Dlg_head *h, int d_key)
  558. {
  559.     Widget_Item *hot_cur;
  560.     Widget_Item *previous;
  561.     int    handled, c;
  562.     extern input_event ();
  563.     
  564.     /* Explanation: we don't send letter hotkeys to other widgets if
  565.        the currently selected widget is an input line */
  566.  
  567.     if (h->current->widget->mouse == input_event){
  568.     if (d_key >= 'A' && d_key <= 'z')
  569.         return 0;
  570.     }
  571.     
  572.     /* If it's an alt key, send the message */
  573.     c = d_key & ~ALT(0);
  574.     if (d_key & ALT(0) && c >= 'A' && c <= 'z')
  575.     d_key = c;
  576.  
  577.      
  578.     handled = 0;
  579.     if (h->current->widget->options & W_WANT_HOTKEY)
  580.     handled = callback (h) (h, h->current->widget, WIDGET_HOTKEY, d_key);
  581.     
  582.     /* If not used, send hotkey to other widgets */
  583.     if (handled)
  584.     return handled;
  585.     
  586.     hot_cur = h->current;
  587.     
  588.     /* send it to all widgets */
  589.     do {
  590.     if (hot_cur->widget->options & W_WANT_HOTKEY)
  591.         handled |= (*hot_cur->widget->callback)
  592.         (h, hot_cur->widget, WIDGET_HOTKEY, d_key);
  593.     
  594.     if (!handled)
  595.         hot_cur = hot_cur->next;
  596.     } while (h->current != hot_cur && !handled);
  597.     
  598.     if (!handled)
  599.     return 0;
  600.  
  601.     (*h->callback) (h, 0, DLG_HOTKEY_HANDLED);
  602.     previous = h->current;
  603.     if (!dlg_unfocus (h))
  604.     return handled;
  605.     
  606.     h->current = hot_cur;
  607.     if (!dlg_focus (h)){
  608.     h->current = previous;
  609.     dlg_focus (h);
  610.     }
  611.     return handled;
  612. }
  613.  
  614. void dlg_key_event (Dlg_head *h, int d_key)
  615. {
  616.     int handled;
  617.     
  618.     /* TAB used to cycle */
  619.     if (!h->raw && d_key == '\t')
  620.     dlg_one_down (h);
  621.     else {
  622.     
  623.     /* first can dlg_callback handle the key */
  624.     handled = (*h->callback) (h, d_key, DLG_KEY);
  625.  
  626.     /* next try the hotkey */
  627.     if (!handled)
  628.         handled = dlg_try_hotkey (h, d_key);
  629.     
  630.     /* not used - then try widget_callback */
  631.     if (!handled)
  632.         handled |= callback (h)(h, h->current->widget, WIDGET_KEY, d_key);
  633.     
  634.     /* not used- try to use the unhandled case */
  635.     if (!handled)
  636.         handled |= (*h->callback) (h, d_key, DLG_UNHANDLED_KEY);
  637.     
  638.     if (!handled)
  639.         dialog_handle_key (h, d_key);
  640.     (*h->callback) (h, d_key, DLG_POST_KEY);
  641.     }
  642. }
  643.  
  644. static INLINE int dlg_mouse_event (Dlg_head *h, Gpm_Event *event)
  645. {
  646.     Widget_Item *item;
  647.     Widget_Item *starting_widget = h->current;
  648.     Gpm_Event   new_event;
  649.     int x = event->x;
  650.     int y = event->y;
  651.     int ret_value;
  652.  
  653.     /* kludge for the menubar: start at h->first, not current  */
  654.     /* Must be carefull in the insertion order to the dlg list */
  655.     if (y == 1 && h->has_menubar)
  656.     starting_widget = h->first;
  657.  
  658.     item = starting_widget;
  659.     do {
  660.     Widget *widget = item->widget;
  661.  
  662.     item = item->next;
  663.     
  664.     if (!((x > widget->x) && (x <= widget->x+widget->cols) 
  665.         && (y > widget->y) && (y <= widget->y+widget->lines)))
  666.         continue;
  667.  
  668.     new_event = *event;
  669.     new_event.x -= widget->x;
  670.     new_event.y -= widget->y;
  671.  
  672.     ret_value = widget->mouse ? (*widget->mouse) (&new_event, widget) :
  673.         MOU_NORMAL;
  674.  
  675.     return ret_value;
  676.     } while (item != starting_widget);
  677.     return 0;
  678. }
  679.  
  680. /* Run dialog routines */
  681.  
  682. /* Amazing, Solaris linker found this problem */
  683. #ifdef HAVE_X
  684. extern widget_data containers [];
  685. extern int containers_no;
  686. #endif
  687.  
  688. /* Init the process */
  689. void init_dlg (Dlg_head *h)
  690. {
  691.     int refresh_mode;
  692.  
  693.     tk_end_frame ();
  694.     
  695.     /* Initialize dialog manager and widgets */
  696.     (*h->callback) (h, 0, DLG_INIT);
  697.     dlg_broadcast_msg (h, WIDGET_INIT, 0);
  698.  
  699.     if (h->x == 0 && h->y == 0 && h->cols == COLS && h->lines == LINES)
  700.     refresh_mode = REFRESH_COVERS_ALL;
  701.     else
  702.     refresh_mode = REFRESH_COVERS_PART;
  703.     push_refresh (dlg_refresh, h, refresh_mode);
  704.     h->refresh_pushed = 1;
  705.     
  706.     /* Initialize direction */
  707.     if (!h->direction)
  708.     h->current =  h->first;
  709.     
  710.     if (h->initfocus != NULL)
  711.         h->current = h->initfocus;
  712.  
  713.     h->previous_dialog = current_dlg;
  714.     current_dlg = h;
  715.     
  716.     /* Initialize the mouse status */
  717.     h->mouse_status = 0;
  718.  
  719.     /* Redraw the screen */
  720.     dlg_redraw (h);
  721.     
  722.     while (!dlg_focus (h))
  723.     h->current = h->current->next;
  724.  
  725.     h->running = 1;
  726. #ifdef HAVE_XVIEW
  727.     if (h != midnight_dlg)
  728.         xvdlg_show(h, h->wdata);
  729.     else {
  730.         int i;
  731.         for (i = 0; i < containers_no; i++)
  732.             x_panel_container_show (containers [i]);
  733.     }
  734. #endif
  735. #ifdef HAVE_TK
  736.     tk_init_dlg (h);
  737. #endif
  738. }
  739.  
  740. /* Shutdown the run_dlg */
  741. void dlg_run_done (Dlg_head *h)
  742. {
  743.     (*h->callback) (h, h->current->dlg_id, DLG_END);
  744.     current_dlg = (Dlg_head *) h->previous_dialog;
  745. #ifdef HAVE_TK
  746.     if (current_dlg){
  747.     char *wdata = (char *) current_dlg->current->widget->wdata;
  748.     tk_evalf ("focus %s", wdata+1);
  749.     }
  750. #endif
  751. }
  752.  
  753. void dlg_process_event (Dlg_head *h, int key, Gpm_Event *event)
  754. {
  755.     if (key == -1){
  756.     if (got_interrupt ())
  757.         key = XCTRL('g');
  758.     else
  759.         return;
  760.     }
  761.     
  762.     if (key == 0)
  763.     h->mouse_status = dlg_mouse_event (h, event);
  764.     else
  765.     dlg_key_event (h, key);
  766. }
  767.  
  768.  
  769. /* Standard run dialog routine
  770.  * We have to keep this routine small so that we can duplicate it's
  771.  * behavior on complex routines like the file routines, this way,
  772.  * they can call the dlg_process_event without rewriting all the code
  773.  */
  774. void run_dlg (Dlg_head *h)
  775. {
  776. #ifndef HAVE_X
  777.     int d_key;
  778.     Gpm_Event event;
  779. #endif
  780.     
  781.     init_dlg (h);
  782. #ifdef HAVE_X
  783. #ifdef HAVE_XVIEW
  784.     xvrundlg_event (h);
  785. #else
  786.     tkrundlg_event (h);
  787. #endif
  788. #else
  789.     event.x = -1;
  790.     while (h->running) {
  791. #ifdef HAVE_SLANG
  792.     /* It does not work with ncurses, it will break */
  793.     if (winch_flag)
  794.         change_screen_size ();
  795. #endif
  796.     if (is_idle ()){
  797.         if (idle_hook)
  798.         execute_hooks (idle_hook);
  799.         
  800.         while (h->send_idle_msg && is_idle ()){
  801.         (*h->callback) (h, 0, DLG_IDLE);
  802.         }
  803.     }
  804.  
  805.     update_cursor (h);
  806.     (*h->callback)(h, 0, DLG_PRE_EVENT);
  807.  
  808.     /* Clear interrupt flag */
  809.     got_interrupt ();
  810.     d_key = get_event (&event, h->mouse_status == MOU_REPEAT);
  811.  
  812.     dlg_process_event (h, d_key, &event);
  813.     }
  814. #endif
  815.     dlg_run_done (h);
  816. }
  817.  
  818. void destroy_dlg (Dlg_head *h)
  819. {
  820.     int i;
  821.     Widget_Item *c;
  822.  
  823.     if (h->refresh_pushed)
  824.     pop_refresh (); 
  825.  
  826.     dlg_broadcast_msg (h, WIDGET_DESTROY, 0);
  827.     c = h->current;
  828.     for (i = 0; i < h->count; i++){
  829.     if (c->widget->destroy)
  830.         c->widget->destroy (c->widget);
  831.     c = c->next;
  832.     free (h->current->widget);
  833.     free (h->current);
  834.     h->current = c;
  835.     }
  836.     if (h->title)
  837.     free (h->title);
  838. #ifdef HAVE_TK
  839.     tk_evalf ("destroy %s", (char *) h->wdata);
  840.     tk_dispatch_all ();
  841.     free ((char *) h->wdata);
  842.     tk_end_frame ();        /* Cleanup, in case I forget */
  843. #endif
  844.     free (h);
  845.     if (refresh_list)
  846.     do_refresh ();
  847. }
  848.  
  849. int std_callback (Dlg_head *h, int Msg, int Par)
  850. {
  851.     return 0;
  852. }
  853.  
  854. void widget_set_size (Widget *widget, int y, int x, int lines, int cols)
  855. {
  856.     widget->x = x;
  857.     widget->y = y;
  858.     widget->cols = cols;
  859.     widget->lines = lines;
  860. }
  861.  
  862. /* Replace widget old for widget new in the h dialog */
  863. void dlg_replace_widget (Dlg_head *h, Widget *old, Widget *new)
  864. {
  865.     Widget_Item *p = h->current;
  866.     int should_focus = 0;
  867.     
  868.     do {
  869.     if (p->widget == old){
  870.  
  871.         if (old == h->current->widget)
  872.         should_focus = 1;
  873.         
  874.         /* We found the widget */
  875.         /* First kill the widget */
  876.         new->focused = old->focused;
  877.         new->parent  = h;
  878.         send_message_to (h, old, WIDGET_DESTROY, 0);
  879.         (*old->destroy) (old);
  880.  
  881.         /* We insert the new widget */
  882.         p->widget = new;
  883.         send_message_to (h, new, WIDGET_INIT, 0);
  884.         if (should_focus){
  885.         if (dlg_focus (h) == 0)
  886.             select_a_widget (h, 1);
  887.         }
  888.         send_message_to (h, new, WIDGET_DRAW, 0);
  889.         break;
  890.     }
  891.     p = p->next;
  892.     } while (p != h->current);
  893. }
  894.  
  895. void widget_redraw (Dlg_head *h, Widget_Item *w)
  896. {
  897.     Widget_Item *save = h->current;
  898.  
  899.     h->current = w;
  900.     (*w->widget->callback)(h, h->current->widget, WIDGET_DRAW, 0);
  901.     h->current = save;
  902. }
  903.  
  904. /* Returns the index of h->current from h->first */
  905. int dlg_item_number (Dlg_head *h)
  906. {
  907.     Widget_Item *p;
  908.     int i = 0;
  909.  
  910.     p = h->first;
  911.  
  912.     do {
  913.     if (p == h->current)
  914.         return i;
  915.     i++;
  916.     p = p->next;
  917.     } while (p != h->first);
  918.     fprintf (stderr, "Internal error: current not in dialog list\n\r");
  919.     exit (1);
  920. }
  921.  
  922. int dlg_select_nth_widget (Dlg_head *h, int n)
  923. {
  924.     Widget_Item *w;
  925.     int i;
  926.  
  927.     w = h->first;
  928.     for (i = 0; i < n; i++)
  929.     w = w->next;
  930.  
  931.     return dlg_select_widget (h, w->widget);
  932. }
  933.  
  934. #ifndef HAVE_XVIEW
  935. void xv_layout (void *first, ...)
  936. {
  937. }
  938. #endif
  939.  
  940. #ifdef HAVE_TK
  941.  
  942. /* Frames must include a trailing dot */
  943. static void tk_frame_proc (Dlg_head *h, char *frame, int new_frame)
  944. {
  945.     char *s = strdup (frame);
  946.     
  947.     if (frame [strlen (frame)-1] != '.'){
  948.     fprintf (stderr, "Invalid frame name\n");
  949.     exit (1);
  950.     }
  951.     s [strlen (frame)-1] = 0;
  952.     the_frame = frame;
  953.     
  954.     if (new_frame)
  955.     tk_evalf ("frame %s.%s", (char *)h->wdata, s);
  956. }
  957.  
  958. /* If passed a null string, it returns */
  959. void tk_new_frame (Dlg_head *h, char *frame)
  960. {
  961.     if (!*frame)
  962.     return;
  963.     tk_frame_proc (h, frame, 1);
  964. }
  965.  
  966. void tk_frame (Dlg_head *h, char *frame)
  967. {
  968.     tk_frame_proc (h, frame, 0);
  969. }
  970.  
  971. void tk_end_frame ()
  972. {
  973.     the_frame = "";
  974. }
  975. #else
  976. void tk_layout (void *first, ...)
  977. {
  978. }
  979.  
  980. void tk_new_frame (Dlg_head *h, char *x)
  981. {
  982. }
  983.  
  984. void tk_frame (Dlg_head *h, char *x)
  985. {
  986. }
  987.  
  988. void tk_end_frame (void)
  989. {
  990. }
  991.  
  992. #ifndef HAVE_XVIEW
  993. void
  994. x_set_dialog_title (Dlg_head *h, char *title)
  995. {
  996.   h->title = strdup(title);
  997. }
  998. #endif
  999.  
  1000. #endif
  1001.  
  1002.